"""
The MIT License (MIT)
Copyright © 2022 Walkline Wang (https://walkline.wang)
Gitee: https://gitee.com/walkline/micropython-esp32-walkie-talkie
"""

'''
| MAX98357A | ESP32 |
|-------------------|
|   LRC <===> IO13  |
|  BCLK <===> IO14  |
|   DIN <===> IO12  |
|   GND <===> GND   |
|   Vin <===> VIN   |
'''
from machine import Pin, I2S
import socket
import _thread
from utils.wifihandler import WifiHandler

BUFF_SIZE = 2000

# wave file
INTERNET_RADIO_HOST = ('http://vis.media-ice.musicradio.com/CapitalMP3', 80)
INTERNET_RADIO_FILE = 'https://gitee.com/walkline/micropython-esp32-walkie-talkie/raw/master/pcm/pingfanzhilu.wav'
INTERNET_RADIO_FILE = 'http://192.168.0.25/pingfanzhilu.wav'

# i2s format
BITS = 16
FORMAT = I2S.MONO
RATE = 16000

class Pins(object):
	BUTTON = 0

	DIN = SD = Pin(12)
	BCLK = SCK = Pin(14)
	LRCLK = WS = Pin(13)


class MAX98357(object):
	def __init__(self):
		self.__audio = I2S(
			1,
			sck=Pins.SCK, 
			ws=Pins.WS,
			sd=Pins.SD,
			mode=I2S.TX,
			bits=BITS,
			format=FORMAT,
			rate=RATE,
			ibuf=BUFF_SIZE
		)


class InternetRadio(MAX98357):
	def __init__(self):
		super().__init__()
		
		self.__wave_samples_mv = memoryview(bytearray(BUFF_SIZE))
		self.__paused = False
		self.__server, code, msg = self.__get_music_file()

		if code == 200:
			print(f'got file, play now...')
			_thread.start_new_thread(self.__loop, ())
		else:
			print(f'get file failed, code: {code}, msg: {msg}')

	def play(self):
		self.__paused = not self.__paused

	def __loop(self):
		while True:
			if not self.__paused:
				self.__server.readinto(self.__wave_samples_mv, BUFF_SIZE)
				# I2S.shift(buf=self.__wave_samples_mv, bits=16, shift=-1)
				self.__audio.write(self.__wave_samples_mv)

	def __get_music_file(self):
		try:
			proto, dummy, host, path = INTERNET_RADIO_FILE.split("/", 3)
		except ValueError:
			proto, dummy, host = INTERNET_RADIO_FILE.split("/", 2)
			path = ""
		if proto == "http:":
			port = 80
		elif proto == "https:":
			import ussl
			port = 443
		else:
			raise ValueError("Unsupported protocol: " + proto)

		if ":" in host:
			host, port = host.split(":", 1)
			port = int(port)

		ai = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
		ai = ai[0]

		s = socket.socket(ai[0], ai[1], ai[2])

		try:
			s.connect(ai[-1])
			if proto == "https:":
				s = ussl.wrap_socket(s, server_hostname=host)
			s.write(b"%s /%s HTTP/1.0\r\n" % ('GET', path))
			s.write(b"\r\n")
			l = s.readline()
			# print(l)
			l = l.split(None, 2)
			status = int(l[1])
			reason = ""
			if len(l) > 2:
				reason = l[2].rstrip()
			while True:
				l = s.readline()
				if not l or l == b"\r\n":
					break
				# print(l)
				if l.startswith(b"Transfer-Encoding:"):
					if b"chunked" in l:
						raise ValueError("Unsupported " + l)
				elif l.startswith(b"Location:") and not 200 <= status <= 299:
					raise NotImplementedError("Redirects not yet supported")
		except OSError:
			s.close()
			raise

		return s, status, reason

def main():
	if WifiHandler.STATION_CONNECTED == WifiHandler.set_sta_mode(timeout_sec=120):
		def button_irq(pin_instance):
			radio.play()

		radio = InternetRadio()
		button = Pin(Pins.BUTTON, Pin.IN)
		button.irq(button_irq, Pin.IRQ_RISING)
	else:
		from machine import reset
		reset()


if __name__ == '__main__':
	main()
